-[ 0x0B ]--------------------------------------------------------------------
-[ e-mule - Curiosidades ]---------------------------------------------------
-[ by FCA00000 ]-----------------------------------------------------SET-34--

Este es un artculo que cuenta algunas cosas sobre el programa eMule usado para transferencia de ficheros en redes P2P.
Incidentalmente se explica el sistema de crditos y como se le puede engaar.
Empiezo de manera sencilla, y voy aumentando el nivel. Salta los prrafos que 
ya sepas.

Introduccin
----------------
La verdad es que sospecho que no hace falta ninguna presentacin para el eMule, 
pero aqu va.
Las redes de intercambio de ficheros P2P llevan mucho tiempo establecidas, y 
existen varias de ellas. De hecho el programa eMule se puede conectar a ms de 
una. El protocolo ms comn se denomina eDonkey.
Existen varios programas clientes P2P pero definitivamente eMule es uno de los 
ms usados. Al ser el cdigo de licencia GPL, se puede ver el cdigo fuente y 
modificarlo.
Para ello slo es necesario el compilador Visual C++ 7.10
Aunque no te lo creas, yo no tengo conexin a Internet en casa. Si quiero mirar 
el correo o mirar alguna pgina web, lo hago desde el trabajo, o en casa de 
algn amigo.
Sin embargo recientemente intent comprar una pelcula que no encontr en 
ninguna tienda, as que me pas al lado oscuro y intent conseguirla en el P2P.
Instal el eMule, me conect a un servidor, la busqu, y estaba disponible en 7 
fuentes, de las cuales 2 estaban desconectadas. No es mucho, pero menos da una 
piedra.

Datos partidos
--------------------
Cuando un ordenador se conecta a un servidor de la red P2P, le dice cuales 
ficheros comparte. En realidad el nombre del fichero no es importante, sino un 
identificador nico para cada fichero. Esto hace que, aunque cambies el nombre, 
el servidor sigue sabiendo que t tienes el mismo fichero que otra persona, si 
los identificadores coinciden.
Por tanto, el servidor almacena los siguientes datos:
-direccin IP del cliente
-nombre del fichero
-identificador nico del fichero

Ahora sera til que consiguieras el documento 'The eMule Protocol 
Specification' disponible en http://emule-project.net. Explica muchas cosas con 
gran detalle.
Para seguir la misma notacin, usar las palabras:
-servidor: es un ordenador conocido, disponible 24x7. Se usa para la 
 autentificacin, para saber los clientes conectados, y los ficheros que stos 
 ofrecen.
-fuente: un ordenador que tiene un fichero
-destino: un ordenador que desea un fichero

Como supongo que todos sabis, cada fuente puede tener el fichero completo, o 
slo un trozo. En cualquier caso, el ordenador destino y el fuente intercambian 
informacin sobre los trozos disponibles, y el fuente decide en qu momento se 
los va a dar.
Esta decisin depende de varias reglas:
-nmero de sesiones: si el fuente tiene muchos clientes, el destino tendr que
 esperar hasta que est desocupado.
-volatilidad: supongamos que un fichero se divide en 10 trozos, y que 1 de
 ellos slo lo tiene 1 fuente. Con el objetivo de asegurar su supervivencia, el
 fuente le da prioridad a este trozo.
-ubicuidad: si un trozo est en otras 1.000 fuentes, se entiende que es fcil
 de conseguir, por lo que no es prioritario.
-antiguedad de la sesin: los primeros 15 minutos van ms rpidos que los
 siguientes.
-trozos intermedios: si un cliente ha bajado muchos trozos, baja su prioridad
 para los siguientes.
-trozos finales: cuando te falta un nico trozo para completar el fichero,
 adquiere prioridad. Esto se hace para evitar una debilidad del protocolo, y la
 frustracin del 'fallo en el ltimo minuto'
-usuarios amigos: es posible promocionar a ciertos clientes, beneficindolos
 con ms velocidad o prioridad.
-crditos: para recompensar a los usuarios donantes, se establece un porcentaje
 entre la cantidad de datos bajados y subidos. Si t me das ficheros a m, yo
 te los doy a t. Quid pro quo, que dira Sneca.

Recordar que el destino le pide trozos al fuente, y ste los pone en una cola 
de la manera que mejor le parezca. Es posible que ests en la posicin 200 y 
de repente saltes a la 4, o incluso vuelvas para atrs porque alguien se te 
haya colado.

Es ms, lo normal es pedirle el mismo trozo a todos los fuentes que lo tienen. 
Cuando te llega el turno, el fuente le pregunta al destino si todava quiere el 
trozo. Si ya lo has conseguido de otro sitio, no lo necesitas.
Pero no vuelves a final de la cola, sino que el fuente pregunta: 'Vale, no 
quieres el trozo X, pero tambin me has pedido el trozo Y . Lo quieres? '

Qu hay de lo mo?
--------------------------
En mi caso concreto, yo buscaba un fichero muy poco comn: 'El hombre que no 
estaba all', dirigida por los hermanos Cohen.
Tras algunas deducciones, entend que los usuarios que comparten este fichero 
son aficionados a todo tipo de cine, y por tanto tienen muchas pelculas, y 
adems poco comunes. Esto provoca que tengan muchas peticiones, que me ponan 
en la cola para 20 das ms tarde!
La regla de volatilidad no se aplicaba en este caso: muchos de los trozos slo 
los tena una fuente.

Dado que era la primera vez que me conectaba, mi puntuacin es la mnima: ni 
comparto ficheros, ni nadie me conoce. Esto me pone el ltimo de la fila.

Lo que yo pretenda era colarme, con alguna excusa. Obviamente fue en este 
momento cuando decid echarle una ojeada al cdigo fuente.

Se compone de unos 300 ficheros de programa en C++ , y como es para Windows, s 
que el 70% del cdigo se destina al interface grfico. El resto est organizado 
en clases. Bueno, decir 'organizado' es mucho: todos los ficheros estn en el 
mismo directorio. Yo no soy quin para criticar, pero lo podran haber hecho 
ms fcil de entender.

Debo aclarar que tanto el programa como la documentacin denominan los 
conceptos Upload y Download desde el punto de vista del fuente. Es decir: no es 
el destino el que baja un fichero, sino que es el fuente el que lo sube.

Lo primero que mir es el sistema de crditos, que est en el fichero 
ClientCredits.cpp
La rutina importante es
CClientCredits::GetScoreRatio(uint32 dwForIP)

que obviamente dice la puntuacin de un cliente. Esta puntuacin se guarda en 
el fuente, no en el servidor. Es decir, yo decido si t me gustas o no.

El programa primero mira el nmero de bytes que se han bajado. Es decir: si tu 
no me has dado ms de 1 Mb, entonces eres un roica, y tu puntuacin es la 
mnima: 1
En cambio si el fuente ha bajado del destino, pero no ha subido nada, entonces 
'esta ronda la pago yo' y tu puntuacin es la mxima: 10
En cualquier otro caso, se dividen la cantidad de datos bajados entre los 
subidos. Hace una interpolacin lineal y otra exponencial, y toma el mejor.

Vale, as que si quiero colarme, tengo que darle antes algo a cambio.

?Bailas?
------------
Mi objetivo es porporcionarle al fuente un fichero que sea apetitoso. En cuanto 
l empiece a bajarlo, me dar crditos y me subir el fichero que yo quiero.
Lo repetir con un ejemplo:
-yo quiero The_man_who_wasnt_there_by_Cohen.avi
-si l quiere The_big_lebowsky_by_Cohen.avi , entonces
-yo busco The_big_lebowsky_by_Cohen.avi en otro fuente.
-lo bajo, y se lo ofrezco.
-consigo puntos a mi favor
-l sube The_man_who_wasnt_there_by_Cohen.avi hacia m


La solucin lgica es ver qu ficheros tiene el fuente parcialmente, sin 
completar, esperando que algn alma caritativa los ponga a su disposicin. 
Seguramente est ansioso por obtenerlos.

Ahora tengo que saber cuales ficheros quiere el fuente. En teora podra usar 
el comando
6.4.21 View shared files
pero por defecto no est habilitado, pues es un ataque a la privacidad del 
fuente.

Mirando la documentacin del eMule en el apartado 6.2.9 explica el protocolo 
para buscar un fichero, pero slo sirve en el servidor. Adems la nica manera 
de buscar un fichero es mediante el nombre, o el identificador nico. No se 
permite hacer una bsqueda usando el usuario como criterio.

Dado que eMule no permite saber todos los ficheros parciales de una fuente (ni 
tampoco los completados), tengo que buscar alguna puerta trasera.

Para saber lo que le interesa a mi fuente, he supuesto ciertas hiptesis que 
luego he ido refinando.

Si el fuente tiene una pelcula de los Cohen, quizs tenga ms. Le digo al 
eMule que busque ficheros que incluyan la palabra 'Cohen'. Obviamente encuentra 
muchas occurrencias, de distintas fuentes.
Lo bueno es que puedo filtrar (en mi cliente eMule) los que pertenecen a una 
cierta fuente, con su direccin IP, o el nombre de usuario.
Esto lo hago en SearchFile.cpp
CSearchFile::CSearchFile
que es donde procesa el mensaje OP_SEARCHRESULT segn se explica en la 
documentacin 6.2.10 Search Result
El filtro compara el campo Client ID, llamado m_nClientID en esta rutina.

Tambin se puede hacer en
BaseClient.cpp
CUpDownClient::ProcessHelloTypePacket
pero esto es para el caso de que solicites el fichero, no para la bsqueda en 
s.

Para esto tengo que modificar y recompilar el eMule. Cuestin de un par de 
minutos.

Con esto averiguo que mi futuro amigo tiene otras 2 pelculas de los Cohen. Las 
tiene completas, as que no est interesado en conseguir los trozos que le 
faltan.
Usando un poquito de ingeniera social, deduzco que quizs le gusten otros 
directores similares. Le digo a eMule que busque archivos conteniendo la 
palabra Triers (por Lars von Triers, supongo que te suena) , Ingar Bergman, y 
similares.
Consulto unas cuantas pginas de cinematografa para hallar trminos 
sub-relacionados con Cohen, y en unos 20 minutos he lanzado 100 bsquedas en 
los servidores eMule, que proporcionan una lista de 30 ficheros pertenecientes 
a mi futuro amigo.

Le pido esos 30 ficheros a mi fuente. Debido al diseo del eMule, el protocolo 
para saber cuales partes estn disponibles, tiene prioridad sobre las colas 
para obtener los trozos de los ficheros. Con esto veo cuales ficheros tiene 
completos, y cuales trozos le faltan.

Obviamente esta tcnica es bastante limitada, pero felizmente resulta efectiva 
y averiguo que tiene 2 ficheros de los que le faltan 1 trozo a cada uno. Uno de 
ellos es Oh_brother_where_are_thou_by_Cohen.avi , que le falta el trozo sptimo.

Esta es la ma: busco quin tiene ese trozo y ... nadie lo tiene. De hecho hay 
15 fuentes parciales; ninguna completa. Notar que esos 15 son a su vez destinos 
potenciales del trozo que nadie tiene. O sea, que si yo tuviera ese trozo, me 
hara amigo de todos ellos, aumentando mi crdito con todos.

Pero de dnde lo saco?
--------------------------
Como dice MakiNavaja: 'Lo que falta se inventa, porque en el barrio sobra 
ciencia'
Para completar las pruebas necesito un servidor del protocolo eDonkey. 
Encuentro uno muy simple llamado eFarm cuyo cdigo fuente ocupa 100 KB y se 
compila e instala en un plisplas.

Hago que un ordenador Linux me funcione como servidor + fuente, y otro Windows 
hace de destino.

Cojo una pelcula cualquiera, la renombro como 
Oh_brother_where_are_thou_by_Cohen.avi , y ahora tengo que modificar su 
identificador nico. Esto se calcula en AbstractFile.cpp
CAbstractFile::SetFileHash

que simplemente llama a md4cpy
ahora hay que mirar el mdulo MD4.cpp para darse cuenta de cmo hace los 
checksums. Bsicamente se parte el fichero en trozos de 9.28 Mb y se hace un 
hash MD4 de cada parte. Luego se hace otro hash con todos los hash parciales. 
A partir de ahora consideramos que el fichero ocupa 9.28 Mb, por lo que 
llamaremos 'trozo' a una serie de bytes de este sub-fichero.

Ahora hay que leer lo que dice la documentacin en el apartado
6.4.4 Request file parts:
Pide a la fuente trozos de un fichero. Un mensaje puede pedir 3 trozos como 
mximo.
Protocolo: 1 byte = 0xE3
Tamao: 4 bytes = tamao de este mensaje
Tipo: 1 byte = 0x47 = OP_REQUESTPARTS
FileID: 16 bytes = identificador nico del fichero (hash de los datos)
Inicio del trozo primero : 4 bytes
Inicio del trozo segundo : 4 bytes
Inicio del trozo tercero : 4 bytes
Fin del trozo primero : 4 bytes
Fin del trozo segundo : 4 bytes
Fin del trozo tercero : 4 bytes

y el correspondiente

6.4.3 Sending file part
Este mensaje contiene un trozo de un archivo para bajar (debera decir subir). 
El tamao del archivo especificado en la cabecera indica el tamao del trozo, 
no el de este mensaje TCP/IP . Se compone de:
Protocolo: 1 byte = 0xE3
Tamao: 4 bytes = tamao de este trozo
Tipo: 1 byte = 0x46 = OP_SENDINGPART
FileID: 16 bytes = identificador nico del fichero (hash de los datos)
Posicin Inicial : 4 bytes
Posicin Final : 4 bytes
Datos: el contenido, que puede estar comprimido

Ahora es cuando viene lo bueno: las fuentes saben que les falta un trozo del 
subfichero llamado FileID, que a su vez es el cheksum que se debera obtener. 
Pero no tienen nadie que se los proporcione.

Entonces es muy fcil engaarlo: genero un fichero, modifico la rutina 
CAbstractFile::SetFileHash para que identifique este trozo con el nombre FileID 
que piden mis amigos, y lo pongo a disposicin del servidor.

Paso a paso:
-busco  Oh_brother_where_are_thou_by_Cohen.avi
-apunto su FileID, ej. 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA
-elijo un fuente cualquiera
-le llamo con el mensaje 6.4.8 Part hashset request
-me responde 6.4.9 Part hashset reply
-esto contiene 60 sub-ficheros, o sea, 60 FileID
-la parte sptima no la tiene nadie. Su FileID=0x77777777 0x77777777 0x77777777 0x77777777
-creo un fichero 7.bin
-modifico CAbstractFile::SetFileHash para que haga
  if(m_strFileName != "7.bin")
     pucFileHash=calcula_hash();  // rutina original, inalterada
  else
     strcpy(pucFileHash, "0x77777777 0x77777777 0x77777777 0x77777777");
-la lnea anterior no es correcta, pero ms o menos se entiende, no?
-le digo a eMule que recargue la lista de ficheros que yo ofrezco
-dado que es el ltimo fichero que le falta a los destinos, constantemente
 estn escaneando para ver si alguien lo oferta
-en menos de 10 minutos tengo los 15 destinos rogndome que les suba el fichero

Obviamente el checksum no es correcto, as que los destinos creen que ha habido 
un error de transmisin y lo solicitan de nuevo. Una y otra vez.

Lo bueno es que 'oficialmente' yo les he transferido datos, por lo que mi 
puntuacin ha subido.
Esto es porque los crditos se conceden en
CClientCredits::AddDownloaded(uint32 bytes, uint32 dwForIP)
que es llamado por 
CUpDownClient::ProcessBlockPacket
el cual es llamado con cada paquete OP_SENDINGPART.

Recordar que el checksum slo se puede calcular cuando se recibe el sub-fichero, 
no cada trozo.

Existe tambin la posibilidad de mandar trozos comprimidos. Si funciona como 
espero, quizs podra mandar un paquete de 100 bytes, diciendo que en realidad 
se descomprime como 100 Kb. Esto multiplicara rpidamente mi puntuacin !

Mirando el cdigo veo que hace
nHeaderSize = sizeof(FileID) + sizeof(Posicin Inicial) + 
sizeof(Posicin Final) ;
uint32 uTransferredFileDataSize = size - nHeaderSize;
credits->AddDownloaded(uTransferredFileDataSize, GetIP());
...
if (packed)
	....

O sea, que los crditos se conceden en funcin de los datos _transmitidos_ , 
no los datos _efectivos_ . No todo iba a ser bonito.

El infinito, y ms all
--------------------------
Notar que esta tcnica se puede extender a todas las fuentes que queramos.
Si quiero ser amigo de todos, puedo ofertar ficheros muy codiciados:
-Invento nombres de fichero al azar, y los busco en los servidores.
-Elijo aquellos que tienen muchas fuentes (>10) pero hay una parte que nadie
 tiene.
-Solicito sus checksums. Simplemente para obtener el FileID de cada trozo.
-Modifico mi eMule para que diga que yo tengo esas partes.
-En cuanto los otros me las pidan, los pongo en la cola a partir de la posicin 1000
-Esto no requiere una conexin rpida. El mayor esfuerzo es buscar los ficheros en el
 servidor.
-Si alguna vez necesito algo de esas fuentes, los pongo al principio de la cola
-Yo les transmito datos falsificados, y ellos me dan crdito.
-Ya puedo empezar a pedirles los ficheros que quiera.
-Se acabaron las esperas.

Claro que engaar no es la mejor manera de hacer amigos, as que no te aconsejo
usar este truco. De hecho, ahora que lo pienso, esto se usa en la cola del 
mdico: hay gente que pide hora a las 10, a las 11, y a las 12. As pueden ir 
a la hora que ms les convenga. Y si llegan a las 11:15 en vez de esperar, te 
intentan convencer de que les dejes pasar porque slo han llegado tarde por 15 
minutos.

De todas maneras sospecho que no es corriente buscar un nico fichero: supongo 
que la gente baja (casi) cualquier cosa que puedan conseguir, y el problema es 
la velocidad de tu conexin, no la disponibilidad de los ficheros.

Si has seguido el razonamiento vers que es fcil inundar las redes P2P con 
ficheros corrompidos, pues el checksum no se calcula en el momento correcto. 
?Quiere esto decir que las entidades de proteccion de derechos de autor pueden 
luchar, informticamente hablando, contra estas redes? Yo creo que s, aunque 
me parece que no lo han intentado lo suficiente.

Esto me lleva a una pregunta: cmo es posible que haya tantos ficheros que 
estn parcialmente en la red? Cuando la primera persona lo pone a disposicin, 
lo normal es que est completo. Y cuando el segundo usuario lo baja, quiero 
suponer que lo baja completo tambin.
Claro que es posible que la primera fuente desaparezca antes de que nadie tenga 
tiempo de bajarlo, pero en ese caso slo otra persona tendr la mitad.
Cuando un tercero busca el fichero, ya sabe que no est completo, y no tiene 
sentido empezar a bajarlo.

Lo nico que se me ocurre es que esto es la Internet, y no tiene porqu ser 
lgico.


En fin, mucho cuidado con los ficheros que bajais y lo que subs.

*EOF*